#include "synchronization.h"

unsigned int totient(unsigned int i);

void putSynMark(sample_t samples) {
    unsigned i, bit;
    unsigned code = (unsigned) SYN_MESSAGE;
    sample_t toValidate = samples;
#if TEST_SYNCHRONIZATION
    unsigned bitGot;
    unsigned bitsOK = 0;
    unsigned bitsNOK = 0;
#endif

    for (i = 0; i < SYN_NBITS; i++) {
        bit = code & 0x00000001;
        code = code >> 1;
        //shift to the left instead of multiply by 2 is faster
        insertBit(toValidate, bit);
#if TEST_SYNCHRONIZATION
        unsigned bitGot = getBit(toValidate);
        if (bit == bitGot) bitsOK++;
        else bitsNOK++;
#endif
        toValidate += SYN_SAMPLES_PER_BIT;
    }
#if TEST_SYNCHRONIZATION
    printf("SYN bits  OK: %d\n", bitsOK);
    printf("SYN bits NOK: %d\n", bitsNOK);
#endif
}

int testSynMark(const sample_t samples) {
    unsigned code = (unsigned) SYN_MESSAGE;
    unsigned int i;
    sample_t toValidate = (sample_t) samples;
    unsigned int bit;
    unsigned int expected;

    for (i = 0; i < SYN_NBITS; i++) {
        expected = code & 0x00000001;
        code = code >> 1;
        bit = getBit(toValidate);
        toValidate += SYN_SAMPLES_PER_BIT;
        if (bit != expected) return 2;
    }
    return 0;
}

void insertBit(sample_t samples, const unsigned bit) {
    float sInt, sExt;
    unsigned int i;
    float d = 0, teta;
    const unsigned int first = 0;
    const unsigned int last = SYN_SAMPLES_PER_BIT - 1;

    //Calculating sInt
    sInt = 0;
    for (i = first + 1; i < last; i++) {
        sInt += samples[i];
    }
    sInt = sInt / (SYN_SAMPLES_PER_BIT - 2);

    //Calculating sExt
    sExt = samples[first] + samples[last];
    sExt = sExt / 2;
    teta = sExt*SYN_PHI;

    if (teta < SYN_MIN_TETA) teta = SYN_MIN_TETA;

    if (bit > 0) {
        if (sInt < sExt + teta) {
            d = sExt + teta - sInt;
            for (i = first + 1; i < last; i++) {
                samples[i] += d;
            }
        }

    }        //Embed a "0"
    else {
        if (sExt < sInt + teta) {
            d = sInt + teta - sExt;
            for (i = first + 1; i < last; i++) {
                samples[i] -= d;
            }
        }
    } // end nextBit != 0
    return;
}

unsigned getBit(const sample_t samples) {
    register float tInt, tExt;
    unsigned i;
    const unsigned int first = 0;
    const unsigned int last = SYN_SAMPLES_PER_BIT - 1;

    //Calculating tInt
    tInt = 0;
    for (i = first + 1; i < last; i++) {
        tInt += samples[i];
    }
    tInt = tInt / (SYN_SAMPLES_PER_BIT - 2);

    //Calculating tExt
    tExt = samples[first] + samples[last];
    tExt = tExt / 2;
    if (tInt > tExt) {
        return 1; /* extracted a 1 */
    }
    return 0; /* extracted a 0 */
}

unsigned int totient(unsigned int i) {
    unsigned int res; /* Result */
    unsigned int j;

    if (i == 1) return 1;

    res = i;

    /* Check for divisibility by every prime number below the square root. */
    /* Start with 2. */
    if (i % 2 == 0) {
        res -= res >> 1;
        do i = i >> 1; while (i % 2 == 0);
    }

    /* Since this doesn't use a list of primes, check every odd number. Ideally, skip past composite numbers.*/
    for (j = 3; j * j <= i; j += 2) {
        if (i % j == 0) {
            res -= res / j;
            do i /= j; while (i % j == 0);
        }
    }

    /* If i>1, then it's the last factor at this point. */
    if (i > 1) res -= res / i;

    /* Return the result. */
    return res;
}
